/*
Copyright [2020] [https://www.xiaonuo.vip]

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

  http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

Snowy采用APACHE LICENSE 2.0开源协议，您在使用过程中，需要注意以下几点：

1.请不要删除和修改根目录下的LICENSE文件。
2.请不要删除和修改Snowy源码头部的版权声明。
3.请保留源码和相关描述文件的项目出处，作者声明等。
4.分发源码时候，请注明软件出处 https://gitee.com/xiaonuobase/snowy
5.在修改包名，模块名称，项目代码等时，请注明软件出处 https://gitee.com/xiaonuobase/snowy
6.若您的项目无法满足以上几点，可申请商业授权，获取Snowy商业授权许可，请在官网购买授权，地址为 https://www.xiaonuo.vip
 */
package vip.xiaonuo.modular.simple.service.impl;

import cn.hutool.cache.Cache;
import cn.hutool.cache.CacheUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.Console;
import cn.hutool.core.lang.Singleton;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.ibatis.cursor.Cursor;
import org.apache.ibatis.session.ResultContext;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionManager;
import org.springframework.transaction.support.TransactionTemplate;
import vip.xiaonuo.core.exception.ServiceException;
import vip.xiaonuo.core.factory.PageFactory;
import vip.xiaonuo.core.pojo.login.SysLoginUser;
import vip.xiaonuo.core.pojo.page.PageResult;
import vip.xiaonuo.core.util.PoiUtil;
import vip.xiaonuo.modular.simple.entity.Simple;
import vip.xiaonuo.modular.simple.enums.SimpleExceptionEnum;
import vip.xiaonuo.modular.simple.mapper.SimpleMapper;
import vip.xiaonuo.modular.simple.param.SimpleParam;
import vip.xiaonuo.modular.simple.result.SimpleResult;
import vip.xiaonuo.modular.simple.service.SimpleService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import vip.xiaonuo.sys.core.cache.MappingCache;
import vip.xiaonuo.sys.core.redis.FastJson2JsonRedisSerializer;
import vip.xiaonuo.sys.modular.org.entity.SysOrg;
import vip.xiaonuo.sys.modular.org.service.SysOrgService;
import vip.xiaonuo.sys.modular.user.entity.SysUser;
import vip.xiaonuo.sys.modular.user.service.SysUserService;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.*;

/**
 * 单表业务service接口实现类
 *
 * @author abled
 * @date 2022-09-24 21:22:14
 */
@Service
public class SimpleServiceImpl extends ServiceImpl<SimpleMapper, Simple> implements SimpleService {

    @Resource
    private SysOrgService sysOrgService;

    @Resource
    private SysUserService sysUserService;

    @Resource
    private SimpleMapper simpleMapper;


    Log log = LogFactory.get();

    @Override
//    @Transactional(readOnly = true)
    public PageResult<SimpleResult> page(SimpleParam simpleParam) {
        QueryWrapper<Simple> queryWrapper = new QueryWrapper<>();
        if (ObjectUtil.isNotNull(simpleParam)) {
            if (ObjectUtil.isNotEmpty(simpleParam.getName())) {
                queryWrapper.like("name", simpleParam.getName());
            }
            // 根据编码（必填唯一性） 查询 code like %code参数%
            if (ObjectUtil.isNotEmpty(simpleParam.getCode())) {
                queryWrapper.like("code", simpleParam.getCode());
            }
            // 根据状态（0：冻结；1：正常） 查询 state like %state参数%
            if (ObjectUtil.isNotEmpty(simpleParam.getState())) {
                queryWrapper.eq("state", simpleParam.getState());
            }
            // 根据类型（字典项：类型a：A；类型b：B） 查询
            if (ObjectUtil.isNotEmpty(simpleParam.getType())) {
                queryWrapper.eq("type", simpleParam.getType());
            }
            // 根据所属机构 查询
            if (ObjectUtil.isNotEmpty(simpleParam.getOrgId())) {
                queryWrapper.eq("org_id", simpleParam.getOrgId());
            }
            // 根据备注信息（非必填） 查询
            if (ObjectUtil.isNotEmpty(simpleParam.getPostscript())) {
                queryWrapper.like("postscript", simpleParam.getPostscript());
            }
            // 根据负责人（编辑、删除、查看） 查询
            if (ObjectUtil.isNotEmpty(simpleParam.getPonPer())) {
                queryWrapper.eq("ponPer", simpleParam.getPonPer());
            }
            // 根据相关人（查看）（多个用户的id，使用;进行分割） 查询
            if (ObjectUtil.isNotEmpty(simpleParam.getRelPer())) {
                queryWrapper.eq("relPer", simpleParam.getRelPer());
            }
        }
        long startTime = System.currentTimeMillis();
        // Java    ctrl + alt + v
        Page<SimpleResult> simplePage = this.baseMapper.page(PageFactory.defaultPage(), queryWrapper);
//        Page<Simple> simplePage = this.page(PageFactory.defaultPage(), queryWrapper);
//        long middle1  = System.currentTimeMillis();
//        log.info("查询分页时间：{}",(middle1 - startTime));
//        // 查询数据库的数据
//        if (ObjectUtil.isNotEmpty(simplePage)){
////            List<SysOrg> sysOrgList = sysOrgService.list();
////            List<SysOrg> sysOrgList = simpleMapper.sysOrgList(new QueryWrapper<>());
////            Map<Long, SysOrg> sysOrgMap = new HashMap<>();
//
//            // 所有的机构的数据
////            CopyOnWriteArrayList<SysOrg> sysOrgList = new CopyOnWriteArrayList<SysOrg>();
////            List<SysOrg> sysOrgList = Collections.synchronizedList(new ArrayList<>());
//
//            Map<Long, SysOrg> sysOrgMap = new ConcurrentHashMap<>();
//            // 组织机构条数
//            int total = sysOrgService.count();
//            // 线程数
//            int num = 6;
//            // 每个线程处理多少条数据
//            int size = (int) Math.ceil(1.0 * total/num);
//            //初始化线程数量 hutool写法
//            CountDownLatch countDownLatch=ThreadUtil.newCountDownLatch(num);
//            for (int i = 0; i < num; i++){
//                int finalI = i * size;
//                int finalI1 = i+1;
//                // hutool写法
//                ThreadUtil.execute(()->{
//                    try {
//                        long t1 = System.currentTimeMillis();
//                        log.info("线程{}开始执行！", finalI1);
//                        // mybaits-plus的写法 select * from limit 参数：i * size 参数：size
////                        sysOrgList.addAll(sysOrgService.list(Wrappers.<SysOrg>lambdaQuery().last(
////                                StrUtil.format("limit {}, {}", Integer.toString(finalI), Integer.toString(size))
////                        )));
//                        // mybaits的写法 4.1
//                        QueryWrapper<SysOrg> qw = new QueryWrapper<>();
//                        qw.last(StrUtil.format("limit {}, {}", Integer.toString(finalI), Integer.toString(size)));
////                        sysOrgList.addAll(simpleMapper.sysOrgList(qw));
//                        // 第一种：流式查询调用
////                        simpleMapper.sysOrgStream(qw, new ResultHandler<SysOrg>() {
////                             @Override
////                             public void handleResult(ResultContext<? extends SysOrg> resultContext) {
//////                                 sysOrgList.add(resultContext.getResultObject());
////                                 sysOrgMap.put(resultContext.getResultObject().getId(), resultContext.getResultObject());
////                             }
////                         });
//                        // 第一种：流式查询调用简写
//                        simpleMapper.sysOrgStream(qw, ctx -> {
////                            sysOrgList.add(ctx.getResultObject());
//                            sysOrgMap.put(ctx.getResultObject().getId(), ctx.getResultObject());
//                        });
//                        // 第二种流式查询调用
////                        try (
////                                Cursor<SysOrg> cursor = simpleMapper.sysOrgStream(new QueryWrapper<>())
////                        ) {
////                            // Iterator<SysOrg> iterator = cursor.iterator();
////                            cursor.forEach(sysOrg -> {
////                                // sysOrgList.add(sysOrg);
////                                 sysOrgMap.put(sysOrg.getId(), sysOrg);
////                            });
////                        }catch (IOException e) {
////                            e.printStackTrace();
////                        }
//                        long t2 = System.currentTimeMillis();
//                        log.info("线程{}执行完毕；当前map容器数据量：{}；线程执行时间：{}", finalI1,sysOrgMap.size(), (t2-t1));
//                    }catch (Throwable e){
//                        e.printStackTrace();
//                    }finally {
//                        // 递减锁存器的计数，如果计数到达零，则释放所有等待的线程
//                        countDownLatch.countDown();
//                    }
//                });
//            }
//            try {
//                // 第三步：使当前线程在锁存器倒计数至零之前一直等待，除非线程被中断
//                // 如果当前的计数为零，则此方法立即返回
//                countDownLatch.await();
//            } catch (InterruptedException e) {
//                e.printStackTrace();
//            }
//
////            long middle2  = System.currentTimeMillis();
////            log.info("查询机构时间："+(middle2 - middle1)+"-sysOrgList数据："+sysOrgList.size());
////            if (ObjectUtil.isNotEmpty(sysOrgList)) {
////                // 准备一个查询容器
////                sysOrgList.forEach(item ->{
////                    sysOrgMap.put(item.getId(), item);
////                });
////            }
//            long middle3  = System.currentTimeMillis();
////            log.info("处理容器时间："+(middle3 - middle2));
//
//            // 人员的查询容器
////            List<SysUser> sysUserList = sysUserService.list();
////            Map<Long, SysUser> sysUserMap = new HashMap<Long, SysUser>();
////            if(ObjectUtil.isNotEmpty(sysUserList)){
////                sysUserList.forEach(item->{
////                    sysUserMap.put(item.getId(), item);
////                });
////            }
//            List<Simple> simpleList = simplePage.getRecords();
//            if (ObjectUtil.isNotEmpty(simpleList)){
//                simpleList.forEach(item->{
//                    // 组织机构的id
//                    Long orgId = item.getOrgId();
//                    // 通过组织机构的id去查询出，机构的名称
//                    if(ObjectUtil.isNotNull(orgId)){
//                        // 查询数据库 链接数据是很耗费性能
//                        SysOrg sysOrg = sysOrgMap.get(orgId);
////                        SysOrg sysOrg = sysOrgService.getById(orgId);
//                        if(ObjectUtil.isNotEmpty(sysOrg) && StrUtil.isNotBlank(sysOrg.getName())){
//                            item.setOrgName(sysOrg.getName());
//                        }
//                    }
////                    // 负责人的逻辑处理
////                    Long ponPer = item.getPonPer();
////                    if(ObjectUtil.isNotEmpty(ponPer)){
////                        SysUser sysUser = sysUserMap.get(ponPer);
////                        if (ObjectUtil.isNotEmpty(sysUser)&& ObjectUtil.isNotEmpty(sysUser.getName())){
////                            item.setPonPerName(sysUser.getName());
////                        }
////                    }
//
////                    // 相关人的处理逻辑（1L;2L）
////                    String relPer = item.getRelPer();
////                    if(ObjectUtil.isNotEmpty(relPer)){
////                        String[] relPerArr = relPer.split(";");
////                        StringBuilder relPerName = new StringBuilder();
////                        Arrays.stream(relPerArr).forEach(relPerId ->{
////                            if (ObjectUtil.isEmpty(relPerId)) {
////                                // 终止本次循环执行，下一次循环
////                                return;
////                            }
////                            SysUser sysUser = sysUserMap.get(Long.parseLong(relPerId));
////                            if (ObjectUtil.isEmpty(sysUser) || ObjectUtil.isEmpty(sysUser.getName())){
////                                return;
////                            }
////                            relPerName.append(sysUser.getName()).append(";");
////                        });
////                        if (ObjectUtil.isNotEmpty(relPerName)){
////                            item.setRelPerName(relPerName.toString());
////                        }
////                    }
//
//                });
//            }
            long endTime = System.currentTimeMillis();
//            log.info("处理机构逻辑时间："+(endTime - middle3));
            log.warn("总时间："+(endTime - startTime));
//        }
        // sql
        return new PageResult<>(simplePage);
    }

    @Override
    public List<Simple> list(SimpleParam simpleParam) {
        return this.list();
    }

    @Override
    public void add(SimpleParam simpleParam) {
        Simple simple = new Simple();
        BeanUtil.copyProperties(simpleParam, simple);
        this.save(simple);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void delete(List<SimpleParam> simpleParamList) {
        simpleParamList.forEach(simpleParam -> {
            this.removeById(simpleParam.getId());
        });
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void edit(SimpleParam simpleParam) {
        Simple simple = this.querySimple(simpleParam);
        BeanUtil.copyProperties(simpleParam, simple);
        this.updateById(simple);
    }

    @Override
    public Simple detail(SimpleParam simpleParam) {
        return this.querySimple(simpleParam);
    }

    /**
     * 获取单表业务
     *
     * @author abled
     * @date 2022-09-24 21:22:14
     */
    private Simple querySimple(SimpleParam simpleParam) {
        Simple simple = this.getById(simpleParam.getId());
        if (ObjectUtil.isNull(simple)) {
            throw new ServiceException(SimpleExceptionEnum.NOT_EXIST);
        }
        return simple;
    }

    @Override
    public void export(SimpleParam simpleParam) {
        List<Simple> list = this.list(simpleParam);
        PoiUtil.exportExcelWithStream("SnowySimple.xls", Simple.class, list);
    }

}
